import * as THREE from 'plug/threejs/three.module';
import * as TWEEN from "@tweenjs/tween.js"
import {MTLLoader} from "plug/threejs/loaders/MTLLoader";
import {OBJLoader} from "plug/threejs/loaders/OBJLoader";
import {OrbitControls} from "plug/threejs/controls/OrbitControls";
import {compareTableData} from "utils/experiment/common/common";

let anime;
let container;
let camera, scene, renderer;
let planes = [];
let fov = 50;
let near = 1;
let far = 4000;
let planenum = 13;
let width = (1550 / 1918 * window.innerWidth).toFixed(0);
let height = (850 / 977 * window.innerHeight).toFixed(0);
let orbitcontrols;
let time = [];//每个飞机的运动时间的数组
let speed = [];
let direction = [];
let Points = [];//途径点的x,y,z
let dots = [];//来模拟飞机的飞行
let temp = [];//用来当链接的中间点
let tween = [];//连接头
let draw_point = [];
let vis = [];
let safeDistance = 250;
let Distance = [];//来记录各个飞机的飞行距离
let rates = [];//飞机碰撞概率
let starttmp = [[-1910, 1190, 0], [-1910, 987, 0], [-1910, 769, 0], [-1910, 514, 0], [-1910, 280, 0], [-1557, 773, 0], [-1200, 773, 0], [-818, 759, 0], [-355, 1198, 0], [-355, 994, 0], [-355, 762, 0], [-355, 500, 0], [-355, 258, 0]];
let start = [[-1910, 1190, 0], [-1910, 987, 0], [-1910, 769, 0], [-1910, 514, 0], [-1910, 280, 0], [-1557, 773, 0], [-1200, 773, 0], [-818, 759, 0], [-355, 1198, 0], [-355, 994, 0], [-355, 762, 0], [-355, 500, 0], [-355, 258, 0]];
let end = [[1000, 250, 0], [1300, 250, 0], [1600, 250, 0], [1900, 250, 0], [2200, 250, 0], [1900, 50, 0], [1600, -150, 0], [1300, -350, 0], [1000, -550, 0], [1300, -550, 0], [1600, -550, 0], [1900, -550, 0], [2200, -550, 0]];
let __this
let lastTime;
let nowTime;
let run = true;

export function destroy() {
  run = false;
  TWEEN.removeAll()
}

export function AnimePlay(_this) {
  run = true;
  planes = [];
  time = [];//每个飞机的运动时间的数组
  speed = [];
  direction = [];
  Points = [];//途径点的x,y,z
  dots = [];//来模拟飞机的飞行
  temp = [];//用来当链接的中间点
  tween = [];//连接头
  draw_point = [];
  vis = [];
  Distance = [];//来记录各个飞机的飞行距离
  rates = [];//飞机碰撞概率
  __this = _this
  anime = document.getElementById('anime_ex2')
  initData();
  init();
}

function inittable() {
  let tableData = []
  for (let i = 0; i < 13; ++i) {
    tableData.push({
      'planeNo': i + 1,
      'posx': (starttmp[i][0]).toFixed(0),
      'posy': (starttmp[i][1]).toFixed(0),
      'posz': (starttmp[i][2]).toFixed(0),
      'rate': '0%',
      'distance': 0
    })
  }
  __this.tableData = tableData
}

function init() {
  container = anime
  // Fov – 相机的视锥体的垂直视野角
  // Aspect – 相机视锥体的长宽比
  // Near – 相机视锥体的近平面
  // Far – 相机视锥体的远平面
  camera = new THREE.PerspectiveCamera(fov, width / height, near, far);
  camera.position.z = 6000;

  scene = new THREE.Scene();
  scene.background = new THREE.Color(0x1A2B47);
  scene.fog = new THREE.Fog(0x87CEFA, 500, 10000);

  // lights

  scene.add(new THREE.AmbientLight(0x666666));

  let light = new THREE.DirectionalLight(0xdfebff, 1);

  light.position.set(50, 200, 100);
  light.position.multiplyScalar(1.3);

  light.castShadow = true;

  light.shadow.mapSize.width = 1024;
  light.shadow.mapSize.height = 1024;

  let d = 1024;

  light.shadow.camera.left = -d;
  light.shadow.camera.right = d;
  light.shadow.camera.top = d;
  light.shadow.camera.bottom = -d;

  light.shadow.camera.far = 1000;

  scene.add(light);

  let onProgress = function (xhr) {
    if (xhr.lengthComputable) {
      if (xhr.loaded === xhr.total) {
        __this.loading.close()
      }
    }
  };

  let onError = function () {
  };
  let manager = new THREE.LoadingManager();
  let mtl = new MTLLoader(manager)
    .load('http://cdn.hsueh.club/plane.mtl', function (materials) {
      materials.preload();
      new OBJLoader(manager)
        .setMaterials(materials)
        .load('http://cdn.hsueh.club/plane.obj', function (object) {
          myloadplane(object);
        }, onProgress, onError);
    });
  inittable();
}

function initData() {
  let tmp = [];
  for (let i = 0; i < planenum; i++) {
    Points[i] = [];
    dots[i] = [];
    tween.push(0);
    draw_point[i] = [];
    rates[i] = 0;
    direction[i] = [];
    speed[i] = [];
    time[i] = [];
    tmp.push(0);
  }
  for (let i = 0; i < planenum; i++) {
    vis.push(tmp);
  }
  for (let i = 0; i < 1000; i++) {
    temp.push(0);
  }
}

//初始化代码
function initString() {
  if (__this.$store.state.ex2.status === 0) {
    let str = '';
    for (let i = 0; i < planenum; i++) {
      str += "#plane " + (i + 1) + "\n";
      str += "setSpeed " + speed[i][0].toFixed(0) + "\n";
      str += "setAngle " + direction[i][0].toFixed(4) + " " + direction[i][1].toFixed(4) + " " + direction[i][2].toFixed(4) + " " + direction[i][3].toFixed(4) + "\n";
      str += "move " + time[i][0].toFixed(1) + "\n";
    }
    __this.code = str
  }
}

function calDistance() {
  for (let i = 0; i < planenum; i++) {
    let a = 0;
    for (let j = 0; j < time[i].length; j++) {
      a += time[i][j] * speed[i][j];
    }
    Distance.push(a);
  }
}

//仅初始化计算方向用
function calDirection() {
  let a, b, c, d;
  for (let i = 0; i < planenum; i++) {
    a = (end[i][1] - planes[i].position.y) / Math.sqrt((end[i][2] - planes[i].position.z) * (end[i][2] - planes[i].position.z) +
      (end[i][0] - planes[i].position.x) * (end[i][0] - planes[i].position.x) + ((end[i][1] - planes[i].position.y) * (end[i][1] - planes[i].position.y)
      ));

    b = Math.sqrt((end[i][2] - planes[i].position.z) * (end[i][2] - planes[i].position.z) +
      (end[i][0] - planes[i].position.x) * (end[i][0] - planes[i].position.x)) / Math.sqrt((end[i][2] - planes[i].position.z) * (end[i][2] - planes[i].position.z) +
      (end[i][0] - planes[i].position.x) * (end[i][0] - planes[i].position.x) + ((end[i][1] - planes[i].position.y) * (end[i][1] - planes[i].position.y)
      ));

    c = (end[i][2] - planes[i].position.z) / Math.sqrt((end[i][2] - planes[i].position.z) * (end[i][2] - planes[i].position.z) +
      (end[i][0] - planes[i].position.x) * (end[i][0] - planes[i].position.x) + ((end[i][1] - planes[i].position.y) * (end[i][1] - planes[i].position.y)
      ));

    d = Math.sqrt((end[i][1] - planes[i].position.y) * (end[i][1] - planes[i].position.y) +
      (end[i][0] - planes[i].position.x) * (end[i][0] - planes[i].position.x)) / Math.sqrt((end[i][2] - planes[i].position.z) * (end[i][2] - planes[i].position.z) +
      (end[i][0] - planes[i].position.x) * (end[i][0] - planes[i].position.x) + ((end[i][1] - planes[i].position.y) * (end[i][1] - planes[i].position.y)
      ));

    if (end[i][2] - planes[i].position.z < 0) {
      b *= -1;
    }
    if (end[i][0] - planes[i].position.x < 0) {
      d *= -1;
    }

    direction[i].push(a);
    direction[i].push(b);
    direction[i].push(c);
    direction[i].push(d);

    let sped;
    sped = Math.sqrt((end[i][2] - planes[i].position.z) * (end[i][2] - planes[i].position.z) +
      (end[i][0] - planes[i].position.x) * (end[i][0] - planes[i].position.x) + ((end[i][1] - planes[i].position.y) * (end[i][1] - planes[i].position.y)
      )) / 5;
    speed[i].push(sped);
    time[i].push(5);
  }
}

//计算每个飞机的途径点
function calDots() {
  for (let i = 0; i < planenum; i++) {
    for (let j = 0; j < time[i].length; j++) {
      let a = speed[i][j] * time[i][j] * direction[i][j * 4 + 1] * direction[i][j * 4 + 3];
      let b = speed[i][j] * time[i][j] * direction[i][j * 4];
      let c = speed[i][j] * time[i][j] * direction[i][j * 4 + 1] * direction[i][j * 4 + 2];

      dots[i][0] += a;
      dots[i][1] += b;
      dots[i][2] += c;

      Points[i].push(dots[i][0]);
      Points[i].push(dots[i][1]);
      Points[i].push(dots[i][2]);
    }
  }
}

//初始化所有数据
function restart() {
  for (let i = 0; i < planenum; i++) {
    planes[i].position.x = start[i][0];
    planes[i].position.y = start[i][1];
    planes[i].position.z = start[i][2];
  }
  initData();
}

//实现物体的运动
function move() {
  //直接链式实现tween
  for (let i = 0; i < planenum; i++) {
    tween[i] = new TWEEN.Tween(planes[i].position).to({
      x: Points[i][0],
      y: Points[i][1],
      z: Points[i][2]
    }, time[i][0] * 1000);
    for (let j = 1; j < time[i].length; j++) {
      temp[j] = new TWEEN.Tween(planes[i].position).to({
        x: Points[i][j * 3],
        y: Points[i][j * 3 + 1],
        z: Points[i][j * 3 + 2]
      }, time[i][j] * 1000);
    }
    if (time[i].length !== 1) {
      tween[i].chain(temp[1]);
      for (let j = 1; j < time[i].length - 1; j++) {
        temp[j].chain(temp[j + 1]);
      }
    }
  }

  for (let i = 0; i < planenum; i++) {
    tween[i].start();
  }
}

function moveRender() {
  //更新Tween
  TWEEN.update();
  let temp;
  let rate;//碰撞概率
  let p1 = 0, p2 = 0;
  let fly = 1;
  let step = 0;
  // 运动过程中显示高度
  for (let i = 0; i < planenum; i++) {
    let dis = (planes[i].position.x - end[i][0]) * (planes[i].position.x - end[i][0])
      + (planes[i].position.y - end[i][1]) * (planes[i].position.y - end[i][1])
      + (planes[i].position.z - end[i][2]) * (planes[i].position.z - end[i][2]);
    if (dis > 100 * 100) {
      fly = 0;
    }
    let minDistance = 100000;//飞机之间的最小距离
    for (let j = 0; j < planenum; j++) {
      if (i !== j) {
        temp = toDistance(planes[i].position, planes[j].position);
        if (temp < minDistance) {
          minDistance = temp;
          p1 = i;
          p2 = j;
        }
      }
    }
    rate = ((-1 / (3 * safeDistance)) * minDistance + 3 / 2) * 55;
    rate = rate.toFixed(1);
    if (rate >= 80 && vis[p1][p2] === 0) {
      let rd = Math.ceil(Math.random() * 10);
      vis[p1][p2] = 1;
      vis[p2][p1] = 1;
      if (rd >= 2) {
        rates[p1] = 100;
        rates[p2] = 100;
        __this.isFly = false;
        let message = "无人机PL" + (p1 + 1) + "和PL" + (p2 + 1) + "发生碰撞！请修改代码！";
        __this.$alert(message, '提示', {
          confirmButtonText: '确定'
        })
      } else {
        step = p1;
      }
    }
    rate = Math.max(0, rate);
    rate = Math.min(100, rate);
    rates[i] = rate;
  }
  __this.fly = fly;
  let tableData = []
  for (let i = 0; i < 13; ++i) {
    tableData.push({
      'planeNo': i + 1,
      'posx': (planes[i].position.x).toFixed(0),
      'posy': (planes[i].position.y).toFixed(0),
      'posz': (planes[i].position.z).toFixed(0),

      'rate': (rates[i] / 10).toFixed(1) + '%',
      'distance': Distance[i].toFixed(0)
    })
  }

  renderer.render(scene, camera);
  nowTime = new Date().getTime()
  // 在状态相同情况下保持五秒以上就视为结束
  if (nowTime - lastTime >= 5000 && compareTableData(tableData, __this.tableData)) {
    lastTime = new Date().getTime()
    __this.isFly = false;
    TWEEN.removeAll()
    __this.codeTrue = true
  } else {
    __this.tableData = tableData
  }
}

function moveAnimate() {
  if (run === false) return
  moveRender();
  if (__this.isFly) {
    requestAnimationFrame(moveAnimate);
  }
}

function myloadplane(object) {
  for (let i = 1; i <= planenum; i++) {
    let ob = object.clone();
    ob.position.x = start[i - 1][0];
    ob.position.y = start[i - 1][1];
    ob.position.z = start[i - 1][2];
    ob.castShadow = true;
    ob.receiveShadow = true;
    ob.name = 'plane' + (i - 1);
    scene.add(ob);
    planes.push(ob);
  }

  for (let i = 0; i < planenum; i++) {
    dots[i].push(planes[i].position.x);
    dots[i].push(planes[i].position.y);
    dots[i].push(planes[i].position.z);
  }

  renderer = new THREE.WebGLRenderer({antialias: true});
  renderer.setPixelRatio(window.devicePixelRatio);
  renderer.setSize(width, height);
  renderer.shadowMap.enabled = true;
  renderer.shadowMap.type = THREE.PCFShadowMap;
  container.appendChild(renderer.domElement);

  initOrbitControl();

  //为了实现拖拽的不停渲染
  calDirection();
  calDots();
  calDistance();
  initString()
  Animate();
}

//轨迹控制器
function initOrbitControl() {
  orbitcontrols = new OrbitControls(camera, renderer.domElement);
  orbitcontrols.enabled = true;
  camera.position.set(0, 500, 3200);
  orbitcontrols.enableDamping = true;
  //是否可以缩放
  orbitcontrols.enableZoom = true;
  //是否自动旋转
  orbitcontrols.autoRotate = false;
  //设置相机距离原点的最远距离
  orbitcontrols.minDistance = 1;
  //设置相机距离原点的最远距离
  orbitcontrols.maxDistance = 5000;

  orbitcontrols.update();
}

function Animate() {
  render();
  // requestAnimationFrame(Animate);
}

function toDistance(p1, p2) {
  return p1.distanceTo(p2);
}

//普通的渲染
function render() {
  renderer.render(scene, camera);
}

export function clickMove(_this) {
  restart()
  _this.codeTrue = false
  time = _this.time
  speed = _this.speed
  direction = _this.direction
  for (let i = 0; i < planenum; i++) {
    planes[i].position.x = start[i][0];
    planes[i].position.y = start[i][1];
    planes[i].position.z = start[i][2];
  }
  vis = [];
  let tmp = [];
  for (let i = 0; i < planenum; i++) {
    dots[i].push(planes[i].position.x);
    dots[i].push(planes[i].position.y);
    dots[i].push(planes[i].position.z);
    tmp.push(0);
  }
  for (let i = 0; i < planenum; i++) {
    vis.push(tmp);
  }
  lastTime = new Date().getTime();
  nowTime = new Date().getTime()
  calDots();
  calDistance();
  move();
  moveAnimate();
}
